#region

using System.IO;
using System.Text;
using System.Text.RegularExpressions;

#endregion

namespace SubVisual
{
    /// <summary>
    /// Strip out the VSS bindings from the solution and project files
    /// Significant code reuse from mcarbenay's project on CodeProject
    /// http://www.codeproject.com/KB/dotnet/RemoveSCCInfo.aspx 
    /// </summary>
    public class VssBindingRemover
    {
        private static readonly Regex _vs2003ProjRegex = new Regex(
            "Scc\\w*\\s*=\\s*'*\\\".*",
            RegexOptions.IgnoreCase
            | RegexOptions.Multiline
            | RegexOptions.CultureInvariant
            | RegexOptions.Compiled
            );

        private static readonly Regex _vs2005ProjRegex = new Regex(
            "\\<Scc\\w*\\>\\w*\\</Scc\\w*\\>.*",
            RegexOptions.IgnoreCase
            | RegexOptions.Multiline
            | RegexOptions.CultureInvariant
            | RegexOptions.Compiled
            );

        /// <summary>
        /// Will remove all of the VSS bindings from Soluition and Project files.
        /// All other files are ignored since they don't have VSS bindings.
        /// </summary>
        /// <param name="filePath">Path to the file.</param>
        public static void RemoveBindings(string filePath)
        {
            if (Path.GetExtension(filePath).Contains("sln"))
            {
                PatchSolutionFile(filePath);
            }

            if (Path.GetExtension(filePath).Contains("proj"))
            {
                PatchProjectFile(filePath);
            }
        }

        private static void PatchSolutionFile(string fileName)
        {
            var tempFileName = Path.GetDirectoryName(fileName) + @"\old-scc-remove-" + Path.GetFileName(fileName);
            var suoFileName = Path.ChangeExtension(fileName, ".suo");

            try
            {
                if (File.Exists(suoFileName))
                {
                    RemoveReadOnlyOnFile(suoFileName);
                    File.Delete(suoFileName);
                }

                File.Move(fileName, tempFileName);
                RemoveReadOnlyOnFile(tempFileName);

                // create a new .sln file with every non scc-related 
                // info from the old .sln
                // DO NOT use File.Open for it may not open the file with the correct
                // encoding.
                var reader = new StreamReader(tempFileName, Encoding.Default);
                var writer = new StreamWriter(fileName, false, Encoding.Default);
                var inSectionSCC = false;
                var currLine = reader.ReadLine();
                while (currLine != null)
                {
                    if (currLine.Trim() == "GlobalSection(SourceCodeControl) = preSolution")
                    {
                        inSectionSCC = true;
                    }
                    else
                    {
                        if (!inSectionSCC)
                        {
                            writer.WriteLine(currLine);
                        }
                        else
                        {
                            if (currLine.Trim() == "EndGlobalSection")
                            {
                                inSectionSCC = false;
                            }
                        }
                    }

                    currLine = reader.ReadLine();
                }
                reader.Close();
                writer.Close();
            }
            finally
            {
                if (File.Exists(tempFileName))
                {
                    File.Delete(tempFileName);
                }
            }
        }

        private static void PatchProjectFile(string fileName)
        {
            var tempFileName = Path.GetDirectoryName(fileName) + @"\old-scc-remove-" + Path.GetFileName(fileName);

            try
            {
                File.Move(fileName, tempFileName);
                RemoveReadOnlyOnFile(tempFileName);

                var reader = new StreamReader(tempFileName, Encoding.Default);
                var fileContents = reader.ReadToEnd();
                reader.Close();

                var writer = new StreamWriter(fileName, false, Encoding.Default);
                writer.Write(UpdateProjFiles(fileContents));
                writer.Close();
            }
            finally
            {
                if (File.Exists(tempFileName))
                {
                    File.Delete(tempFileName);
                }
            }
        }

        private static string UpdateProjFiles(string fileContents)
        {
            return _vs2003ProjRegex.IsMatch(fileContents)
                       ? _vs2003ProjRegex.Replace(fileContents, string.Empty)
                       : _vs2005ProjRegex.Replace(fileContents, string.Empty);
        }

        private static void RemoveReadOnlyOnFile(string path)
        {
            var attributes = File.GetAttributes(path);
            if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
            {
                File.SetAttributes(path, attributes & (~FileAttributes.ReadOnly));
            }
        }
    }
}